Subject: Re: The meaning of library base ptrs
From: [email-masked] (Ralph Babel)
Date: 12 Jan 1994 14:39:45 +0100
Newsgroups: comp.sys.amiga.programmer,comp.sys.amiga.datacomm

Douglas L Thain wrote:

> _every_ task/process is required to call OpenLibrary
> explicitly, as per C= instructions.  This technique has
> been incidentally valid on previous releases, but has
> never been legal.

This is not true.

Up to and including 1.2, the official documentation never
even mentioned that topic, and several of the example
programs provided by Commodore and its engineers _did_ share
library base pointers, so it was clearly _not_ required to
reopen every library in a subtask.

As of Workbench 1.3, the only _exceptions_ (i.e. it was
_still_ legal to share all _other_ libraries' base pointers)
were the IEEE libraries, which Dale Luck had rewritten to
support the 6888x and arbitrary other coprocessors (see [1,
2]). This did not really have anything to do with different
library _bases_, though, but with the support for non-6888x
coprocessors via the MathIEEE.resource, as Exec saves and
restores the FPU context only for 6888x-compatible
coprocessors automatically upon task switches. Dale
suggested that the MathIEEE.resource patch tc_Switch and
tc_Launch for that purpose (via the TaskOpenLib call-back).

Under 2.x, someone (who - as Hans put it - should probably
be embarrassed :-) decided that unique library bases for
every opener might be a useful concept (which I don't
doubt), but made the mistake of declaring this the new
default behavior (see [3]).

The problem lies not so much with application programs
spawning new tasks, as these application subtasks generally
make use of local per-task data anyway, and reopening all
libraries and keeping their bases as part of that local data
segment is trivial. It may be somewhat of a problem to make
your high-level-language compiler automatically use these
"local" base symbols, but this is completely beside the
point.

The real problem lies with shared libraries (or devices)
based on other shared libraries the functions of which are
called on the schedule of the client of the higher-level
library. If - as some people claim - _all_ "sub"-libraries
have to be reopened for _every_ opener/client/task of the
higher-level library, this requires that either

(a) all calls to lower-level libraries be deferred to a
    global library task to ensure that the library base
    obtained once during library initialization is used only
    from the task that originally opened the library. This
    would introduce two extra task switches for every
    library call. Have fun!

(b) _All_ such libraries (and I really mean _all_ of them) -
    even if they _don't_ require that any per-client data be
    kept by the library itself - suddenly have to create and
    return a new instance of the library base structure upon
    every OpenLibrary() to hold the base addresses of all
    libraries that are used by any of _its_ function
    entries. (As somebody else already pointed out, this may
    also cause problems with SetFunction().)

Neither of these two approaches seems desirable, so I
maintain that the best solution would be to assume that all
library base pointers - UNLESS EXPLICITLY DOCUMENTED NOT TO
BE SHARABLE - _can_ be reused in subtasks. It may be
unnecessary to depend on that assumption if one is merely
writing application programs or SAS-style libraries, but for
properly designed libraries/APIs that require that a context
structure be allocated explicitly by the caller and freed
upon exit, anything else doesn't make sense. This would have
been possible for ixemul.library and socket.library, too,
had they added an extra pointer parameter to (the internal
versions of) all library functions. No-one said that this
extra parameter would have to be visible externally; it may
well be hidden inside a stub function that loads a global
symbol into the appropriate parameter register, similar to
the library base symbols in the amiga.lib stubs.

To cut a long story short: There's only _one_ solution:
Library base pointers _must_ be sharable by _default_.
_Exceptions_ to that rule are permissible, but must be
documented as such explicitly.

Time to fix the RKMs.

References:

[1] RKM Libraries & Devices, 1.3 edition, page 547.

[2] AmigaMail, volume 1, pages XIII-5 to XIII-7.

[3] RKM Libraries, 2.0 edition, page 467.